#include <iostream>
#include <string>
#include <utility>
#include <vector>

#include <boost/any.hpp>

using namespace std;
using namespace boost;

typedef unsigned int uint32_t;
typedef unsigned long uint64_t;

class A
{
   public:
      void some_function() {cout << "A::some_function" <<endl;}
};
 
class B
{
   public:
      void some_function() {cout << "B::some_function" <<endl;}
};

class C
{
   public:
      void some_function() {cout << "C::some_function" <<endl;}
};

void print_any(any& a)
{
   if (A* pA = any_cast<A>(&a)) {
      pA->some_function();
   }
   else if (B* pB = any_cast<B>(&a)) {
      pB->some_function();
   }
   else if (C* pC = any_cast<C>(&a)) {
      pC->some_function();
   }
   else {
      try {
         cout<<any_cast<string>(a) <<endl;
      }
      catch(bad_any_cast&) { 
         cout<<"Opps!"<<endl;
      }
   }
}

int main()
{
   cout<<"Example of using any."<<endl;

   vector<any> store_anything;

   store_anything.push_back(A());
   store_anything.push_back(B());
   store_anything.push_back(C());

   store_anything.push_back(string("This is fantastic!"));
   store_anything.push_back(3);
   store_anything.push_back(make_pair(true, 7.92));

   for_each(store_anything.begin(), store_anything.end(), print_any);

   int32_t i32 = -100;
   int64_t i64 = -100;
   uint32_t ui32 = 100;
   uint64_t ui64 = 100;

   boost::any aint ;
   try {
      aint= i32;
      cout << any_cast<uint32_t>(aint) << endl;
   }
   catch (bad_any_cast&) {

      aint = ui32;
      cout << any_cast<uint32_t>(aint) << endl;
   } 
}

